package com.yjd.job;

import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.springframework.scheduling.quartz.CronTriggerBean;

import com.alibaba.fastjson.JSON;
import com.yjd.comm.annotation.ServiceRemoteProxy;
import com.yjd.comm.asynmsg.enums.TaskMsgTypeEnum;
import com.yjd.comm.asynmsg.model.TaskMsgModel;
import com.yjd.comm.asynmsg.service.ITaskMsgService;
import com.yjd.comm.asynmsg.util.AsynMsgUtil;
import com.yjd.comm.enums.RpcJobExecStatus;
import com.yjd.job.model.JobLogModel;
import com.yjd.job.model.JobModel;
import com.yjd.job.service.IJobLogService;
import com.yjd.job.service.IJobService;
import com.yjd.comm.rpm.RpmServiceKeyEnum;
import com.yjd.comm.util.FrameUtil;
import com.yjd.comm.util.SpringContextHolder;
import com.yjd.comm.util.StringUtil;

/**
 * <b>description</b>：定时器基本job，提供scheduler对象用于热变更定时器配置参数 <br>
 * <b>time</b>：2014-8-22 下午7:14:54 <br>
 * <b>author</b>： ready likun_557@163.com
 */
public abstract class BaseJob {

	protected Logger logger = Logger.getLogger(this.getClass());

	/**
	 * job执行者
	 * 
	 * @return
	 */
	protected abstract boolean doExecute() throws Exception;

	/**
	 * 获取job的类型
	 * 
	 * @return
	 */
	protected abstract String getJobType();

	/**
	 * job是否正在执行
	 */
	private boolean isExecute = false;

	@SuppressWarnings("unchecked")
	public int execute(){

		/**
		 * 如果job正在执行，直接返回成功
		 * 否则，执行job
		 */
		int result = RpcJobExecStatus.SUCCESS.getValue();
		if( !isExecute ){
			// 开始执行 将job状态置为执行中
			isExecute = true;

			result=executer();

			// 执行完毕 将job状态置为当前未执行
			isExecute = false;
			if(result==RpcJobExecStatus.FAILURE.getValue()){
				try {
					Long now =FrameUtil.getTime();
					JobModel job=this.jobService.getJobModelByType(getJobType());
					if(job!=null){
						if(job.getRetry_times() >= job.getFail_times()){
							TaskMsgModel task=new TaskMsgModel();
							task.setMsg_type(TaskMsgTypeEnum.job_re_excue.getMsgType());
							task.setExtend_data(JSON.toJSONString(job));
							task.setPlan_ex_time(now+AsynMsgUtil.delay_time);
							task.setMax_failure(1);
							task.setRef_id(job.getId_job()+"");
							task.setStatus(0);
							task.setFailure(0);
							task.setCreate_time(now);
							this.taskMsgService.inserts(FrameUtil.newArrayList(task));
						}
					}
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
			}
		}

		return result;
	}
	
	public int executer() {
		try {
			this.jobModel = this.jobService.getJobModelByType(getJobType());
			if (this.jobModel != null) {
				/**
				 * 定时器的cron改变了
				 */
				if (changeCorn(this.jobModel.getCron())) {
					return RpcJobExecStatus.ERROR1.getValue();
				}
				/**
				 * 当前job不可用
				 */
				if (this.jobModel.getEnable() != 1) {
					return RpcJobExecStatus.ERROR2.getValue();
				}
				// 执行
				JobLogModel jobLogModel = new JobLogModel();
				jobLogModel.setIdJob(this.jobModel.getId_job());
				jobLogModel.setStartTime(FrameUtil.getTime(null));
				boolean isSuccess = false;
				try {
					long start = System.currentTimeMillis();
					logger.info(this.jobModel.getDescription() + " start");
					isSuccess = doExecute();
					logger.info(this.jobModel.getDescription() + " end, cost(ms):"+(System.currentTimeMillis() - start));
					CronTriggerBean trigger = (CronTriggerBean) this.getScheduler().getTrigger(this.getTriggerName(),Scheduler.DEFAULT_GROUP);
					this.jobModel.setLast_exectime(FrameUtil.getTime(trigger.getPreviousFireTime()));
					this.jobModel.setNext_exectime(FrameUtil.getTime(trigger.getNextFireTime()));
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
					jobLogModel.setDescription(e.getMessage());
				}
				jobLogModel.setStatus(isSuccess ? 1 : 0);
				if (isSuccess) {
					String msg = FrameUtil.getResource("normal.00001");
					if (StringUtil.isEmpty(msg)) {
						msg = "执行成功!";
					}
					jobLogModel.setDescription(msg);
					jobModel.setFail_times(0);
				}else{
					jobModel.setFail_times(jobModel.getFail_times()+1);
				}
				this.jobService.update(jobModel);
				jobLogModel.setEndTime(FrameUtil.getTime(null));
				// 记录日志
				this.jobLogService.insert(jobLogModel);
				if (isSuccess) {
					return RpcJobExecStatus.SUCCESS.getValue();
				}else{
					return RpcJobExecStatus.FAILURE.getValue();
				}
			} else {
				// 如果jobmodel不存在，则创建，然后插入库中
				this.jobModel = new JobModel();
				this.jobModel.setCreate_time(FrameUtil.getTime(null));
				this.jobModel.setType(this.getJobType());
				this.jobModel.setCron(getJobCron());
				this.jobModel.setEnable(1);
				CronTriggerBean trigger = (CronTriggerBean) this.getScheduler().getTrigger(this.getTriggerName(),Scheduler.DEFAULT_GROUP);
				jobModel.setLast_exectime(FrameUtil.getTime(trigger.getPreviousFireTime()));
				jobModel.setNext_exectime(FrameUtil.getTime(trigger.getNextFireTime()));
				this.jobService.insert(this.jobModel);
				return RpcJobExecStatus.SUCCESS.getValue();
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return RpcJobExecStatus.FAILURE.getValue();
		}
	}
	

	/**
	 * 若定时器的cron改变了，则重新设置执行时间，返回执行时间是否改变了
	 * 
	 * @param cron
	 * @return
	 * @throws Exception
	 */
	protected boolean changeCorn(String cron) throws Exception {
		boolean isChange = false;
		if (null != this.getScheduler()) {
			Scheduler s = this.getScheduler();
			CronTriggerBean t = null;
			JobDetail jd = null;
			t = (CronTriggerBean) s.getTrigger(this.getTriggerName(),
					Scheduler.DEFAULT_GROUP);
			jd = s.getJobDetail(this.getJobDetailName(),
					Scheduler.DEFAULT_GROUP);
			// 判断cornExpress与当前运行值是否一致
			if (!cron.equals(t.getCronExpression())) {
				s.deleteJob(jd.getName(), s.getJobGroupNames()[0]);
				t.setCronExpression(cron);
				s.scheduleJob(jd, t);
				isChange = true;
			}
		}
		return isChange;
	}

	/**
	 * 获取job的cron
	 * 
	 * @return
	 * @throws Exception
	 */
	public String getJobCron() throws Exception {
		return ((CronTriggerBean) this.getScheduler().getTrigger(
				this.getTriggerName(), Scheduler.DEFAULT_GROUP))
				.getCronExpression();
	}

	/**
	 * trigger的名称
	 */
	private String triggerName;
	/**
	 * jobdetail的名称
	 */
	private String jobDetailName;
	/**
	 * 
	 */
	private JobModel jobModel;
	/**
	 * job服务接口
	 */
	@ServiceRemoteProxy(serviceUrlResouceKey = RpmServiceKeyEnum.RPM_JOB_SERVICE_KEY)
	protected IJobService jobService;

	@ServiceRemoteProxy(serviceUrlResouceKey = RpmServiceKeyEnum.RPM_JOB_SERVICE_KEY)
	protected IJobLogService jobLogService;
	
	@ServiceRemoteProxy
	protected ITaskMsgService taskMsgService;

	/**
	 * scheduler的bean名称
	 */
	private String schedulerBeanName;

	public Scheduler getScheduler() {
		return SpringContextHolder.getBean(this.getSchedulerBeanName());
	}

	public String getTriggerName() {
		return triggerName;
	}

	public void setTriggerName(String triggerName) {
		this.triggerName = triggerName;
	}

	public String getJobDetailName() {
		return jobDetailName;
	}

	public void setJobDetailName(String jobDetailName) {
		this.jobDetailName = jobDetailName;
	}

	public JobModel getJobModel() {
		return jobModel;
	}

	public void setJobModel(JobModel jobModel) {
		this.jobModel = jobModel;
	}

	public String getSchedulerBeanName() {
		return schedulerBeanName;
	}

	public void setSchedulerBeanName(String schedulerBeanName) {
		this.schedulerBeanName = schedulerBeanName;
	}

}
